/*
    Marv the Miner v1.2.0 - For Nokia Series 30, 40 and 60 and for selected MIDP 1.0 supported phones
    Copyright (C) 2003-2004  Digital Entertainment Europe AS (http://www.digiment.no)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
	
    If you have any questions, please contact support@digiment.no
*/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
import java.io.*;
import java.util.*;

public class Miner extends javax.microedition.midlet.MIDlet implements RecordFilter, RecordComparator
{
    static int T_SOUND		= 0;		// record type for setup value
    static int T_LAST		= 1;		// record type for last level passed
    static int T_VIBRA		= 2;		// record type for vibra setup
    static int T_UID			= 3;		// record type for UID
    static int T_INTERNET 	= 4;		// record type for internet setup

	
    Main main = null;
    int isFirst = 1;

    RecordStore rs = null;
    String str,player = "Player";

    int menuLevel = 0;			// which menu is active
    int level = 0;
    int muteSound = 1;
    int useVibra = 0;
    Display disp = null;

    int s_l = 0;
    int s_s = 0;
    int s_f = -1;

    int hsid = 0;
    int i;
    boolean cheats = false;
    boolean paused = false;
//    boolean useInternet = true;
    boolean inited = false;
    boolean isDemo = true;
    int demoLevels = 5;

    public Miner()
    {
    }

    void init()
    {
    	if (inited) return;

    	try
    	{
			rs = RecordStore.openRecordStore("Miner",false);
		}
		catch(Exception ex)
		{
	    	try
    		{
				rs = RecordStore.openRecordStore("Miner",true);
				player = "DEE";
				putRecord(32000,0,1100);
				player = "DEE";
				putRecord(32000,0,1200);
				player = "DEE";
				putRecord(32000,0,1300);
				player = "DEE";
				putRecord(32000,0,1400);
				player = "DEE";
				putRecord(32000,0,1500);
				player = "DEE";
				putRecord(32000,0,1600);
				player = "DEE";
				putRecord(32000,0,1700);
				player = "DEE";
				putRecord(32000,0,1800);
				player = "DEE";
				putRecord(32000,0,2000);
			}
			catch(Exception ex2)
			{
				ex2.printStackTrace();
			}
		}

        muteSound = getVar(T_SOUND);
        useVibra = getVar(T_VIBRA);
//        useInternet = getVar(T_INTERNET) == 1;

        main = new Main();
        Main.midlet = this;
    	Main.initStaticData();

        main.init(Display.getDisplay(this),0);

    	main.securityCode += 9025;
        
		main.start();

        cheats = true;
        inited = true;
    }

    public void startApp() 
    {
        init();
    	
		Displayable currentDisplay = Display.getDisplay(this).getCurrent();
        if (currentDisplay == null) s();
    }

    void s()
    {	
    	set(main);
    	main.running = true;

    }

    void set(Displayable s)
    {
		Display.getDisplay(this).setCurrent(s); 
    }
    
    void startMenu()
    {
       	menuLevel = 0;
       	returnMenu();
    }

    void endGame()
    {
    	menuLevel = 0;
    }

    void returnMenu()
    {
    	if (paused) menuLevel = 10;
		paused = false;
        switch (menuLevel)
        {
	        case 0:
	        	main.running = false;
				if (cheats) level = Main.maxLevel;
				else level = readMaxLevel();
                main.initMenu("Miner",true,false);
				main.addItem("New game");
				main.addItem(main.s_w <= 100 ? "Select lvl" : "Select level");
				main.addItem("Hiscores");
				main.addItem("Options");
				main.addItem("Help");
				main.addItem("About");
				main.addItem("Quit");
				main.menuLast = false;
				main.running = true;
		        set(main);
				break;
			case 1:
				main.running = false;
				main.initMenu("Select level",true,false);
                for (int i = level; i >= 0; i--)
                {
                	str = main.names[i];
                	if (str == null) str = " ";
	           		if ((str.length() + 5) * 8 >= main.s_w) 
	           			str = str.substring(0,(main.s_w / 8) - 7) + "...";

                	if (i < 10)
                		main.addItem(String.valueOf(i + 1) + ". ^" + str);
                	else
                		main.addItem(String.valueOf(i + 1) + ".^" + str);
                }
				main.menuLast = false;
                main.running = true;
		        set(main);
                break;
            case 2:
				main.running = false;
				main.menuLast = true;
				main.initMenu("Hiscores",false,false);
            	bestScores();
                main.running = true;
		        set(main);
            	break;
            case 10:
				main.running = false;
				main.menuLast = false;
				main.initMenu("Pause menu",true,false);
				main.addItem("Resume");
				main.addItem("Exit level");
				main.addItem("Options");
				main.addItem("Help");
				main.addItem("Quit");
                main.running = true;
		        set(main);
            	break;
            	
			default: break;
		}
    }

    void setupOk()
    {
    	muteSound = main.getState(0) ? 0 : 1;
    	useVibra = main.getState(1) ? 1 : 0;
//    	useInternet = main.getState(2);
    	putVar(T_SOUND,muteSound);
    	putVar(T_VIBRA,useVibra);
//    	putVar(T_INTERNET,useInternet ? 1 : 0);
    	menuLevel = 0;
    	returnMenu();
    }

    void editOk(String newName)
    {
		player = newName;
		if (newName.equals("dee")) cheats = true;
		putRecord(hsid,0,main.scores);
/*
		if (useInternet) 
		{
			main.sendScore(player,main.scores);
			if (main.place != -1)
			{
				main.initPlaceScreen();
				main.running = true;
				set(main);
			}
			else
			{
				menuLevel = 2;
    			returnMenu();
			}
		}
		else
*/
		{

			menuLevel = 2;
    		returnMenu();
		}
    }

    void editBack()
    {
		menuLevel = 0;
    	returnMenu();
    }

    void menuBack()
    {
    	switch (menuLevel)
    	{
    		case 1:
    		case 2:
    		case 3: gc();
    				returnMenu();
    				break;
    		default:
                    exitRequested();
                    break;
    	}
    }

    void menuOk(int n)
    {
    	switch (menuLevel)
    	{
    		case 0:

             	if (n == 0)
             	{
           			gc();
           			main.release();
					main.state = 98;
					main.scores = 0;
					main.init(Display.getDisplay(this),0);
       	           	s();
//                main.scores = 1000;
//                editOk("dee");
             	}
            	else
            	if (n == 1)
            	{
	             			// if new game - select level
					menuLevel = 1;
					returnMenu();
            	}
            	else
            	if (n == 2)
            	{
            		menuLevel = 2;
            		returnMenu();
                }
            	else
            	if (n == 3)
            	{
            		menuLevel = 1;
					main.running = false;
					main.initMenu("Options",true,true);
					main.addItem("Sound",muteSound == 0);
					main.addItem("Vibra",useVibra == 1);
//					main.addItem("Internet",useInternet);
					main.addItem("Back",false);
					main.menuLast = false;
    	            main.running = true;
			        set(main);
                }
            	else
            	if (n == 4)
            	{
            		// help
			    	menuLevel = 1;
					main.running = false;
					main.initMenu("Help",false,false);
					main.addText(
						"Use keys 4 and 6 to move Marv left and right. 1,2 and 3 jumps left,up and right. "+
						"5 jumps in the direction Marv is facing. * Brings up the pause menu. "+
						"Guide Marv the Miner through the mines in his search for juvles. "+
						"Make sure to run over all platforms. Places that have been visited are marked. "+
						"All platforms must be marked to reach next level.");
					main.menuLast = true;
			        main.running = true;
			        set(main);
            	}
            	else
            	if (n == 5)
            	{
            		// about
			    	menuLevel = 1;
					main.running = false;
					main.initMenu("About",false,false);
					main.addText(
						"Marv The Miner v.1.2.0 Copyright (c) 2003 Digital Entertainment Europe AS. "+
						"For support, email support@digiment.no. Check out more of our games at www.digiment.no");
					main.menuLast = true;
			        main.running = true;
			        set(main);
            	}
                else
                {
                	exitRequested();
                }
                break;
    		case 1:       // select level
    			int i = level - main.menuIndex;
                gc();
       			main.release();
   	           	main.state = 98;
   	           	main.scores = 0;
				main.init(Display.getDisplay(this),i);
   	           	s();
	           	break;
    		case 3: 
    			gc();
   				returnMenu();
   				break;
   			case 10: // pause menu
   				paused = true;
   				if (n == 0)
   				{
   					// continue
         			main.startTime += System.currentTimeMillis() - main.leaveTime;
         			main.bonusTime += System.currentTimeMillis() - main.leaveTime;
           			gc();
           			main.state = 0;
					s();
   				}
   				else
   				if (n == 1)
   				{
   					// exit level
		        	main.running = false;
		        	main.release();
   					menuLevel = 0;
   					paused = false;
   					returnMenu();
   				}
   				else
   				if (n == 2)
   				{
   					// options
   					menuLevel = 0;
   					menuOk(3);
   				}
   				else
   				if (n == 3)
   				{
   					// help
   					menuLevel = 0;
   					menuOk(4);
   				}
   				else
   				{
   					// quit
   					exitRequested();
   				}
	        default: break;
    	}
    }

    void gc()
    {
    	menuLevel = 0;
    	System.gc();
    }

    void storeScores()
    {
    	int id,found = 0,min = main.scores;
    	hsid = 32000;
   		startRead("*");
   	    while ((id = readNext()) != -1) 
		{
   			if ((r_level == 0) && (r_score > 0) && (r_player.charAt(0) != '#'))
			{
   		    	found = 1;
   		    	if (r_score < min)
   		    	{
   		    		hsid = id;
   		    		min = r_score;
   		    	}
    	    }
      	}

  	    if ((found == 0) || (hsid != 32000)) 
  	    {
    		main.running = false;
    		main.initEditor("NAME:");
    		main.running = true;
			set(main);
    	}
    	else
    	{
    		menuLevel = 0;
    		returnMenu();
    	}
    }

	String filter = null;

	// part of interface
    public boolean matches(byte[] candidate) throws IllegalArgumentException
    {
		if (this.filter == null) return false;
		if (this.filter.equals("*")) return true;

		DataInputStream in = new DataInputStream(new ByteArrayInputStream(candidate));
		String name = null;
		try 
		{
	    	int score = in.readInt();
		    name = in.readUTF();
		}
		catch (Exception ex) {}
		return (this.filter.equals(name));
    }

	public int compare(byte[] rec1, byte[] rec2)
    {
		DataInputStream in1 = new DataInputStream(new ByteArrayInputStream(rec1));
		DataInputStream in2 = new DataInputStream(new ByteArrayInputStream(rec2));
		int s1 = 0;
		int s2 = 0;
		try 
		{
		    s1 = in1.readInt();
		    s2 = in2.readInt();
		}
		catch (Exception ex) {}
		if (s1 < s2) 
			return RecordComparator.PRECEDES;
		else
		if (s1 > s2) 
			return RecordComparator.FOLLOWS;
		else 
	    	return RecordComparator.EQUIVALENT;
    }

    int r_level,r_score;
	String r_player = null;
    RecordEnumeration re = null;

    void startRead(String f)
    {
    	try 
    	{
	    	filter = f;
			re = rs.enumerateRecords(null, this, true);
    	}
    	catch (Exception ex) {}
    }

    int readNext()
    {
    	try 
    	{
	    	if (re.hasNextElement())
    		{
    			int id = re.nextRecordId();
	    		DataInputStream in = new DataInputStream(new ByteArrayInputStream(rs.getRecord(id)));
			    r_level = in.readInt();
			    r_score = in.readInt();
			    r_player = in.readUTF();
	    		return id;
	    	}
    	}
    	catch (Exception ex) {}
    	return -1;
    }

    int getVar(int type)
    {
    	startRead("#");		
   	    while(readNext() != -1) 
			if (r_player.charAt(0) == '#')
    			if (r_level == type) return r_score;
    	return 0;
    }

    void putVar(int type,int value)
    {
    	int foundId = -1,id;
    	startRead("#");		
   	    while((id = readNext()) != -1) 
			if (r_player.charAt(0) == '#')
    			if (r_level == type) 
    				foundId = id;
    	String oldPlayer = player;
    	player = "#";
		putRecord(foundId,type,value);
		player = oldPlayer;
    }

    int readMaxLevel()
    {
    	return getVar(T_LAST);
	}
	
    void storeLevel(int new_level)
    {
    	int id,foundId = -1,maxLevel = 0;
    	startRead("#");
   	    while (((id = readNext()) != -1) && (foundId == -1)) 
   	    {
		   	if ((r_player.charAt(0) == '#') && (r_level == T_LAST))
	    	{
		    	foundId = id;
        		if (maxLevel < r_score) maxLevel = r_score;
    	    }
    	}
   	    if ((maxLevel <= new_level) || (foundId == -1))
   	    {
	    	player = "#";
   	    	putRecord(foundId,T_LAST,new_level);
   	    }
    }

	void bestScores()
	{
		Hashtable h = new Hashtable();
		String str,ssc;
		int score,i,j;
		Integer ii;
  		startRead("*");
		while (readNext() != -1) 
		{
   		    if ((r_level == 0) && (r_score >= 0) && (r_player.charAt(0) != '#'))
			{
				h.put(new Integer(r_score),r_player);
				if (r_player.equals("dee")) cheats = true;
   		    }
		}
		as = new int[h.size()];
		Enumeration e = h.keys();
		for (i = 0; i < as.length; i++)
		{
			as[i] = ((Integer)e.nextElement()).intValue();
		}
		sort(0,as.length - 1);

		for (j = as.length - 1, i = 0; (i < 9) && (j >= 0); i++, j--)
		{
			str = (String)h.get(new Integer(as[j]));
			if (str.length() < 2) str += " ";
			if (str.length() < 3) str += " ";
			ssc = as[j] + "";
			if (as[j] < 10) ssc = "0" + ssc;
			if (as[j] < 100) ssc = "0" + ssc;
			if (as[j] < 1000) ssc = "0" + ssc;
			if (as[j] < 10000) ssc = "0" + ssc;
			main.addItem((i + 1) + ".&" + str + "%" + ssc);
		}
		as = null;
		e = null;
		h = null;
		System.gc();
	}

	int as[] = null;
	int part(int l, int r)
	{
		int i,j;
		int v,b;
		v = as[r];
		i = l - 1;
		j = r;
		do
		{
			do
			{
				j--;
			}
			while ((as[j] > v) && (j != (i + 1)));

			do
			{
				i++;
			}
			while ((as[i] < v) && (i != (j - 1)));
			b = as[i];
			as[i] = as[j];
			as[j] = b;
		}
		while (i < j);
		as[j] = as[i];
		as[i] = as[r];
		as[r] = b;
		return i;
	}

	// QuickSort procedure: arr - any array, l - lower index, t - upper index
	void sort(int l,int t)
	{
		int i;
		if (l < t) 
		{
			i = part(l,t);
			sort(l,i-1);
			sort(i+1,t);
		}
	}

    void putRecord(int remove_id,int l,int s)
    {
    	try
    	{
    		ByteArrayOutputStream baos = new ByteArrayOutputStream();
    		DataOutputStream out = new DataOutputStream(baos);
    		out.writeInt(l);
    		out.writeInt(s);
    		out.writeUTF(player);
    		byte[] b = baos.toByteArray();

			if ((remove_id != 32000) && (remove_id != -1)) rs.setRecord(remove_id, b, 0, b.length);
			else rs.addRecord(b, 0, b.length);
    	}
    	catch(Exception ex){}
    }

    public void pauseApp() {}
    
    public void destroyApp(boolean unconditional) {}

    void exitRequested()
    {
    	if (main != null) main.stop();
        destroyApp(false);
        notifyDestroyed();
    }
}

